//
//  RNScreenCapture.m
//  RNScreenCapture
//
//  Created by GJS on 2018/9/7.
//  Copyright © 2018年 GJS. All rights reserved.
//

#import "RNScreenCapture.h"
#import "UtilFileCacheForScreenCapture.h"
#import <Photos/Photos.h>

@implementation RNScreenCapture {
    BOOL observerAdded;
}

NSString *const kScreenCapture = @"ScreenCapture";

RCT_EXPORT_MODULE(ScreenCapture)

- (instancetype)init
{
    self = [super init];
    if (self) {
        //注册通知
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(userDidTakeScreenshot:)
                                                     name:UIApplicationUserDidTakeScreenshotNotification object:nil];
        observerAdded = YES;
    }
    return self;
}

- (void)dealloc {
    //移除通知
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    observerAdded = NO;
}

#if __has_include(<React/RCTEventEmitter.h>)
/**
 * These methods will be called when the first observer is added and when the
 * last observer is removed (or when dealloc is called), respectively. These
 * should be overridden in your subclass in order to start/stop sending events.
 */
- (void)startObserving
{
    //
    if (!observerAdded) {
        //注册通知
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(userDidTakeScreenshot:)
                                                     name:UIApplicationUserDidTakeScreenshotNotification object:nil];
    }
}

- (void)stopObserving
{
    //
    //移除通知
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    observerAdded = NO;
}

- (NSArray<NSString *> *)supportedEvents{
    return @[
             kScreenCapture,
             ];
}
#endif

- (void)postMessgeNotif:(NSDictionary *)data messageType:(NSString *)type{
    
#if __has_include(<React/RCTEventEmitter.h>)
    if (self.bridge) {
        [self sendEventWithName:type body:data];
    }
#else
    if (self.bridge) {
        [self.bridge.eventDispatcher sendDeviceEventWithName:type
                                                        body:data];
    }
#endif
    
}

//开始监听
RCT_REMAP_METHOD(startListener, startListenerResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
    if (!observerAdded) {
        //注册通知
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(userDidTakeScreenshot:)
                                                     name:UIApplicationUserDidTakeScreenshotNotification object:nil];
    }
    if (resolve) {
        resolve(@YES);
    }
}

//停止监听
RCT_EXPORT_METHOD(stopListener){
    //移除通知
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    observerAdded = NO;
}

//截屏响应
- (void)userDidTakeScreenshot:(NSNotification *)notification
{
    NSLog(@"检测到截屏");
    
    //人为截屏, 模拟用户截屏行为, 获取所截图片
    //UIImage *image_ = [self imageWithScreenshot];
    NSData *data = [self dataWithScreenshotInPNGFormat];
    if (data) {
        NSString *uuid = [NSUUID UUID].UUIDString;
        NSString *image_path = [NSString stringWithFormat:@"%@.png", uuid];
        NSString *imagePath = [[UtilFileCacheForScreenCapture instance].cachePath stringByAppendingPathComponent:image_path];
        BOOL stored = [[UtilFileCacheForScreenCapture instance] storeFile:data toPath:imagePath];
        if (stored) {
            [self postMessgeNotif:@{@"imagePath": imagePath} messageType:kScreenCapture];
        }
    }
    
//    // 尝试删除最新的截图
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//        [self getWaterMarkImage];
//    });
}

- (void)getWaterMarkImage {
    PHFetchResult *collectonResuts = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAny options:[PHFetchOptions new]] ;
    [collectonResuts enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        PHAssetCollection *assetCollection = obj;
        if ([assetCollection.localizedTitle isEqualToString:@"All Photos"])  {
            PHFetchResult *assetResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:[PHFetchOptions new]];
            id obj = [assetResult lastObject];
            if (obj) {
                // 在资源的集合中获取第一个集合，并获取其中的图片
                PHAsset *asset = obj;
                [asset requestContentEditingInputWithOptions:nil completionHandler:^(PHContentEditingInput * _Nullable contentEditingInput, NSDictionary * _Nonnull info) {
                    // 似乎删除不了
//                    BOOL deleted = [[UtilFileCacheForScreenCapture instance] removeFile:contentEditingInput.fullSizeImageURL.absoluteString];
//                    NSLog(@"deleted:%d", deleted);
                    // 得到一张 UIImage，展示到界面上
                    UIImage *finalImage = [self.class getWaterMarkImage:contentEditingInput.displaySizeImage andTitle:@"水印~~" andMarkFont:[UIFont systemFontOfSize:UIFont.systemFontSize] andMarkColor:UIColor.greenColor];
                    // 3、创建PHAdjustmentdata，可以在data参数里设置要做的操作，比如过滤等，可以是一个序列串，但是这里的长度是有限制的
                    PHAdjustmentData * adjustData = [[PHAdjustmentData alloc] initWithFormatIdentifier:asset.localIdentifier formatVersion:@"1.0" data:[@"ceshi" dataUsingEncoding:NSUTF8StringEncoding]];
                    // 4、初始化PHContentEditingOutput对象
                    PHContentEditingOutput * output = [[PHContentEditingOutput alloc] initWithContentEditingInput:contentEditingInput];
                    output.adjustmentData = adjustData;
                    // 通过PHContentEditingInput可以获取到想要的信息，处理图片:修改图片整体颜色
//                    NSURL * imageUrl = [contentEditingInput fullSizeImageURL];  // 包含图片数据的文件
//                    NSData * originalImageData = [NSData dataWithContentsOfURL:imageUrl];
//                    UIImage * originalImage = [UIImage imageWithData:originalImageData];
                    
                    // ⚠️这里为什么一定要用UIImageJPEGRepresentation才能成功，而UIImagePNGRepresentation会失败，生成的数据是正确的，但是相册相应的资源无法更新???
                    // 因为这个和renderedContentURL有关，图片的输出只能是JPEG格式，video只能是.mov格式输出
                    // 对于Live Photo，调用saveLivePhotoToOutput:options:completionHandler:方法保存和更新
                    BOOL isSuccess = [UIImageJPEGRepresentation(finalImage, 1) writeToURL:output.renderedContentURL atomically:NO];
                    if (isSuccess) {
                        NSLog(@"写入成功");
                    } else {
                        NSLog(@"写入失败");
                    }
                    
                    // 5、赋值更新
                    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
                        // 使用PHAssetChangeRequest
                        PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest changeRequestForAsset:asset];
                        changeRequest.contentEditingOutput = output;
                    } completionHandler:^(BOOL success, NSError *error) {
                        if (success) {
                            NSLog(@"编辑内容成功");
                        } else {
                            NSLog(@"编辑内容失败:%@", error);
                        }
                    }];
                }];
            }
            
            *stop = YES;
        }
    }];
}

//截屏响应
- (void)userDidTakeScreenshot1:(NSNotification *)notification
{
    // 这里的 userDidTakeScreenshot 总共做了3件事
    // 1.打印检测到截屏
    // 2.获取截屏图片。调用[self imageWithScreenshot]; 这里的imageWithScreenshot是人为截屏, 模拟用户截屏操作, 获取截屏图片。
    // 3.显示截屏图片, 以屏幕1/4大小显示在右下角, 并且加上白色边框和阴影效果突出显示。
    
    NSLog(@"检测到截屏");
    
    //人为截屏, 模拟用户截屏行为, 获取所截图片
    UIImage *image_ = [self imageWithScreenshot];
    
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    
    //添加显示
    UIImageView *imgvPhoto = [[UIImageView alloc]initWithImage:image_];
    imgvPhoto.frame = CGRectMake(window.frame.size.width/2, window.frame.size.height/2, window.frame.size.width/2, window.frame.size.height/2);
    
    //添加边框
    CALayer * layer = [imgvPhoto layer];
    layer.borderColor = [
                         [UIColor whiteColor] CGColor];
    layer.borderWidth = 5.0f;
    //添加四个边阴影
    imgvPhoto.layer.shadowColor = [UIColor blackColor].CGColor;
    imgvPhoto.layer.shadowOffset = CGSizeMake(0, 0);
    imgvPhoto.layer.shadowOpacity = 0.5;
    imgvPhoto.layer.shadowRadius = 10.0;
    //添加两个边阴影
    imgvPhoto.layer.shadowColor = [UIColor blackColor].CGColor;
    imgvPhoto.layer.shadowOffset = CGSizeMake(4, 4);
    imgvPhoto.layer.shadowOpacity = 0.5;
    imgvPhoto.layer.shadowRadius = 2.0;
    
    [window addSubview:imgvPhoto];
}

/**
 *  截取当前屏幕
 *
 *  @return NSData *
 */
- (NSData *)dataWithScreenshotInPNGFormat
{
    CGSize imageSize = CGSizeZero;
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    if (UIInterfaceOrientationIsPortrait(orientation))
        imageSize = [UIScreen mainScreen].bounds.size;
    else
        imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
    
    UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    for (UIWindow *window in [[UIApplication sharedApplication] windows])
    {
        CGContextSaveGState(context);
        CGContextTranslateCTM(context, window.center.x, window.center.y);
        CGContextConcatCTM(context, window.transform);
        CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y);
        if (orientation == UIInterfaceOrientationLandscapeLeft)
        {
            CGContextRotateCTM(context, M_PI_2);
            CGContextTranslateCTM(context, 0, -imageSize.width);
        }
        else if (orientation == UIInterfaceOrientationLandscapeRight)
        {
            CGContextRotateCTM(context, -M_PI_2);
            CGContextTranslateCTM(context, -imageSize.height, 0);
        } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
            CGContextRotateCTM(context, M_PI);
            CGContextTranslateCTM(context, -imageSize.width, -imageSize.height);
        }
        if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)])
        {
            [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES];
        }
        else
        {
            [window.layer renderInContext:context];
        }
        CGContextRestoreGState(context);
    }
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return UIImagePNGRepresentation(image);
}

/**
 *  返回截取到的图片
 *
 *  @return UIImage *
 */
- (UIImage *)imageWithScreenshot
{
    NSData *imageData = [self dataWithScreenshotInPNGFormat];
    return [UIImage imageWithData:imageData];
}

#define HORIZONTAL_SPACE 30//水平间距
#define VERTICAL_SPACE 50//竖直间距
#define CG_TRANSFORM_ROTATION (M_PI_2 / 3)//旋转角度(正旋45度 || 反旋45度)
/**
 根据目标图片制作一个盖水印的图片
 
 @param originalImage 源图片
 @param title 水印文字
 @param markFont 水印文字font(如果不传默认为23)
 @param markColor 水印文字颜色(如果不传递默认为源图片的对比色)
 @return 返回盖水印的图片
 */
+ (UIImage *)getWaterMarkImage: (UIImage *)originalImage andTitle: (NSString *)title andMarkFont: (UIFont *)markFont andMarkColor: (UIColor *)markColor{
    
    UIFont *font = markFont;
    if (font == nil) {
        font = [UIFont systemFontOfSize:23];
    }
    UIColor *color = markColor;
    if (color == nil) {
        color = [self mostColor:originalImage];
    }
    //原始image的宽高
    CGFloat viewWidth = originalImage.size.width;
    CGFloat viewHeight = originalImage.size.height;
    //为了防止图片失真，绘制区域宽高和原始图片宽高一样
    UIGraphicsBeginImageContext(CGSizeMake(viewWidth, viewHeight));
    //先将原始image绘制上
    [originalImage drawInRect:CGRectMake(0, 0, viewWidth, viewHeight)];
    //sqrtLength：原始image的对角线length。在水印旋转矩阵中只要矩阵的宽高是原始image的对角线长度，无论旋转多少度都不会有空白。
    CGFloat sqrtLength = sqrt(viewWidth*viewWidth + viewHeight*viewHeight);
    //文字的属性
    NSDictionary *attr = @{
                           //设置字体大小
                           NSFontAttributeName: font,
                           //设置文字颜色
                           NSForegroundColorAttributeName :color,
                           };
    NSString* mark = title;
    NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:mark attributes:attr];
    //绘制文字的宽高
    CGFloat strWidth = attrStr.size.width;
    CGFloat strHeight = attrStr.size.height;
    
    //开始旋转上下文矩阵，绘制水印文字
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    //将绘制原点（0，0）调整到源image的中心
    CGContextConcatCTM(context, CGAffineTransformMakeTranslation(viewWidth/2, viewHeight/2));
    //以绘制原点为中心旋转
    CGContextConcatCTM(context, CGAffineTransformMakeRotation(CG_TRANSFORM_ROTATION));
    //将绘制原点恢复初始值，保证当前context中心和源image的中心处在一个点(当前context已经旋转，所以绘制出的任何layer都是倾斜的)
    CGContextConcatCTM(context, CGAffineTransformMakeTranslation(-viewWidth/2, -viewHeight/2));
    
    //计算需要绘制的列数和行数
    int horCount = sqrtLength / (strWidth + HORIZONTAL_SPACE) + 1;
    int verCount = sqrtLength / (strHeight + VERTICAL_SPACE) + 1;
    
    //此处计算出需要绘制水印文字的起始点，由于水印区域要大于图片区域所以起点在原有基础上移
    CGFloat orignX = -(sqrtLength-viewWidth)/2;
    CGFloat orignY = -(sqrtLength-viewHeight)/2;
    
    //在每列绘制时X坐标叠加
    CGFloat tempOrignX = orignX;
    //在每行绘制时Y坐标叠加
    CGFloat tempOrignY = orignY;
    for (int i = 0; i < horCount * verCount; i++) {
        [mark drawInRect:CGRectMake(tempOrignX, tempOrignY, strWidth, strHeight) withAttributes:attr];
        if (i % horCount == 0 && i != 0) {
            tempOrignX = orignX;
            tempOrignY += (strHeight + VERTICAL_SPACE);
        }else{
            tempOrignX += (strWidth + HORIZONTAL_SPACE);
        }
    }
    //根据上下文制作成图片
    UIImage *finalImg = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    CGContextRestoreGState(context);
    return finalImg;
}

//根据图片获取图片的主色调
+(UIColor*)mostColor:(UIImage*)image{
    
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1
    int bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
#else
    int bitmapInfo = kCGImageAlphaPremultipliedLast;
#endif
    //第一步 先把图片缩小 加快计算速度. 但越小结果误差可能越大
    CGSize thumbSize=CGSizeMake(image.size.width/2, image.size.height/2);
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL,
                                                 thumbSize.width,
                                                 thumbSize.height,
                                                 8,//bits per component
                                                 thumbSize.width*4,
                                                 colorSpace,
                                                 bitmapInfo);
    
    CGRect drawRect = CGRectMake(0, 0, thumbSize.width, thumbSize.height);
    CGContextDrawImage(context, drawRect, image.CGImage);
    CGColorSpaceRelease(colorSpace);
    
    //第二步 取每个点的像素值
    unsigned char* data = CGBitmapContextGetData (context);
    if (data == NULL) return nil;
    NSCountedSet *cls=[NSCountedSet setWithCapacity:thumbSize.width*thumbSize.height];
    
    for (int x=0; x<thumbSize.width; x++) {
        for (int y=0; y<thumbSize.height; y++) {
            int offset = 4*(x*y);
            int red = data[offset];
            int green = data[offset+1];
            int blue = data[offset+2];
            int alpha =  data[offset+3];
            if (alpha>0) {//去除透明
                if (red==255&&green==255&&blue==255) {//去除白色
                }else{
                    NSArray *clr=@[@(red),@(green),@(blue),@(alpha)];
                    [cls addObject:clr];
                }
                
            }
        }
    }
    CGContextRelease(context);
    //第三步 找到出现次数最多的那个颜色
    NSEnumerator *enumerator = [cls objectEnumerator];
    NSArray *curColor = nil;
    NSArray *MaxColor=nil;
    NSUInteger MaxCount=0;
    while ( (curColor = [enumerator nextObject]) != nil )
    {
        NSUInteger tmpCount = [cls countForObject:curColor];
        if ( tmpCount < MaxCount ) continue;
        MaxCount=tmpCount;
        MaxColor=curColor;
        
    }
    return [UIColor colorWithRed:([MaxColor[0] intValue]/255.0f) green:([MaxColor[1] intValue]/255.0f) blue:([MaxColor[2] intValue]/255.0f) alpha:([MaxColor[3] intValue]/255.0f)];
}

@end
